package com.dferreira.languagesteach.activities;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import com.dferreira.languagesteach.R;
import com.dferreira.languagesteach.activities.generic.IFragmentStack;
import com.dferreira.languagesteach.fragments.LanguagesFragment;
import com.dferreira.languagesteach.fragments.generic.NavigationListFragment;
import com.dferreira.languagesteach.helpers.GenericUI;
import com.dferreira.languagesteach.utils.ApplicationState;

import java.util.Stack;

public class NavigationActivity extends FragmentActivity implements IFragmentStack {

    private static final String TAG = "NavigationListActivity";
    private static final String SAVED_FRAGMENTS_CLASSES_STACK_KEY = TAG + ":FRAGMENTS_CLASSES_STACK";
    private static final String SAVED_FRAGMENTS_PACKAGES_FOLDER_STACK_KEY = TAG + ":FRAGMENTS_PACKAGES_FOLDER";

    private boolean restoredActivity;
    private Stack<Fragment> fragmentsStack;
    private Stack<String> fragmentsClassesStack;
    private Stack<String> fragmentsPackageFoldersStack;

    /**
     * Called when the activity is starting.  This is where most initialization
     *
     * @param savedInstanceState If the activity is being re-initialized after
     *                           previously being shut down then this Bundle contains the data it most
     *                           recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.navigation_list);
        restoredActivity = false;
    }

    /**
     *
     */
    public void onStart(){
        super.onStart();
    }

    /**
     * @param className
     * @param packageFolder
     * @return
     */
    private Fragment createFragmentThroughClassName(String className, String packageFolder) {
        Class<?> clazz;
        try {
            clazz = Class.forName(className);
            NavigationListFragment fragment = (NavigationListFragment) clazz.newInstance();
            fragment.setArguments(packageFolder, this);
            return fragment;
        } catch (ClassNotFoundException e) {
            Log.w(TAG, e);
        } catch (InstantiationException e) {
            Log.w(TAG, e);
        } catch (IllegalAccessException e) {
            Log.w(TAG, e);
        }

        return null;
    }

    /**
     *
     */
    private void restoreFragmentsStack() {
        this.fragmentsStack = new Stack<Fragment>();
        for (int i = 0; i < this.fragmentsClassesStack.size(); i++) {
            String className = fragmentsClassesStack.get(i);
            String packageFolder = fragmentsPackageFoldersStack.get(i);
            this.fragmentsStack.push(createFragmentThroughClassName(className, packageFolder));
        }
        setFragmentInView(this.fragmentsStack.peek());
    }

    /**
     * Ensures the list view has been created before Activity restores all
     * of the view states.
     *
     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
     */
    @SuppressWarnings("NullableProblems")
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        if (savedInstanceState != null) {
            this.fragmentsClassesStack = (Stack<String>) savedInstanceState.getSerializable(SAVED_FRAGMENTS_CLASSES_STACK_KEY);
            this.fragmentsPackageFoldersStack = (Stack<String>) savedInstanceState.getSerializable(SAVED_FRAGMENTS_PACKAGES_FOLDER_STACK_KEY);
            this.restoreFragmentsStack();

            restoredActivity = true;
        }
    }

    private void setFragmentInView(Fragment fragment){
        /*TODO improve this*/
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_content, fragment);
        fragmentTransaction.commit();
    }

    /**
     * @param fragment
     */
    public void pushFragment(Fragment fragment) {
        this.fragmentsStack.push(fragment);
        this.fragmentsClassesStack.push(((Object) fragment).getClass().getName());
        this.fragmentsPackageFoldersStack.push(((NavigationListFragment) fragment).getPackageFolder());
        setFragmentInView(fragment);
    }

    /**
     *
     */
    private void freshStart() {
        if (!restoredActivity) {
            this.fragmentsStack = new Stack<Fragment>();
            this.fragmentsClassesStack = new Stack<String>();
            this.fragmentsPackageFoldersStack = new Stack<String>();
            LanguagesFragment languagesFragment = new LanguagesFragment();
            languagesFragment.setFragmentStack(this);
            pushFragment(languagesFragment);
        }
    }

    /**
     * Dispatch onResume() to fragments.  Note that for better inter-operation
     * with older versions of the platform, at the point of this call the
     * fragments attached to the activity are <em>not</em> resumed.  This means
     * that in some cases the previous state may still be saved, not allowing
     * fragment transactions that modify the state.  To correctly interact
     * with fragments in their proper state, you should instead override
     * {@link #onResumeFragments()}.
     */
    @Override
    protected void onResume() {
        super.onResume();
        freshStart();
    }


    /**
     * @param menu a reference to the menu
     * @return always will be true
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return GenericUI.onCreateOptionsMenu(this, menu);
    }

    /**
     * This hook is called whenever an item in your options menu is selected.
     *
     * @param item which was selected
     * @return always will return false
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        GenericUI.onOptionsItemSelected(this, item);
        return super.onOptionsItemSelected(item);
    }


    /**
     * @param requestCode The integer request code originally supplied to
     *                    startActivityForResult(), allowing you to identify who this
     *                    result came from.
     * @param resultCode  The integer result code returned by the child activity
     *                    through its setResult().
     * @param data        An Intent, which can return result data to the caller
     *                    (various data can be attached to Intent "extras").
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == GenericUI.RESULT_CORRUPTED_PACKAGE) {
            setResult(resultCode, data);
            super.onBackPressed();
        }
    }


    /**
     * Will restore a session
     *
     * @param applicationState path to the subject that needs to be restored
     */
    public void restorePath(ApplicationState applicationState) {
        applicationState.getLanguagePrefix();
    }

    /**
     * @param savedInstanceState Bundle in which is placed the saved state.
     */
    @SuppressWarnings("NullableProblems")
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putSerializable(SAVED_FRAGMENTS_CLASSES_STACK_KEY, this.fragmentsClassesStack);
        savedInstanceState.putSerializable(SAVED_FRAGMENTS_PACKAGES_FOLDER_STACK_KEY, this.fragmentsPackageFoldersStack);
    }
}
